home *** CD-ROM | disk | FTP | other *** search
- #pragma implementation
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/wait.h>
- #include <signal.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include "misc.h"
- #include "popen.h"
-
- PUBLIC POPEN::POPEN(const char *command)
- {
- pid = -1;
- status = -1;
- int fdout[2];
- int fderr[2];
- if (pipe(fdout)!=-1 && pipe(fderr)!=-1){
- pid = fork();
- if (pid == 0){
- close (fdout[0]);
- close (fderr[0]);
- dup2 (fdout[1],1);
- dup2 (fderr[1],2);
- close (fdout[1]);
- close (fderr[1]);
- setuid (geteuid());
- int ret = system (command);
- _exit (ret);
- }
- close (fdout[1]);
- close (fderr[1]);
- fds.out = fdout[0];
- fds.err = fderr[0];
- }
- }
-
- PUBLIC POPEN::~POPEN()
- {
- if (pid != -1){
- kill (pid,SIGTERM);
- waitend();
- }
- close (fds.out);
- close (fds.err);
- }
-
- /*
- Wait until the process is really dead and recover its end status
- */
- PRIVATE void POPEN::waitend ()
- {
- while (1){
- int code = ::wait(&status);
- if (code == pid) break;
- fprintf (stderr,"code = %d\n",code);
- }
- pid = -1;
- }
-
- /*
- Return != 0 if the pipe is corretly opened
- */
- PUBLIC int POPEN::isok()
- {
- return pid != -1;
- }
-
- PRIVATE void POPEN::readif (struct fd_set *in, int fd, SSTRING &buf)
- {
- if (FD_ISSET(fd,in)){
- char bufread[10000];
- int len = read (fd,bufread,sizeof(bufread)-1);
- if (len > 0){
- bufread[len] = '\0';
- buf.append (bufread);
- }else{
- // end of process
- waitend();
- }
- }
- }
-
-
- /*
- Wait for anything to be available from the child process
- Return -1 if any error.
- Return 0 if the timeout has elapsed.
- Return 1 if there is some data to read
- */
- PUBLIC int POPEN::wait(int timeout)
- {
- int ret = -1;
- if (pid != -1){
- struct fd_set in;
- FD_ZERO(&in);
- FD_SET (fds.out,&in);
- FD_SET (fds.err,&in);
- struct timeval tim;
- tim.tv_usec = 0;
- tim.tv_sec = timeout;
- int maxfd = fds.err > fds.out ? fds.err : fds.out;
- ret = select (maxfd+1,&in,NULL,NULL,&tim);
- readif (&in,fds.out,outbuf);
- readif (&in,fds.err,errbuf);
- }
- return ret;
- }
-
- /*
- Return the status code of the ending process
- */
- PUBLIC int POPEN::getstatus()
- {
- return status;
- }
-
- /*
- Read one complete line or up to size byte in "line".
- If there is no complete line, nothing is read
- */
- PRIVATE int POPEN::readline (char *line, int size, SSTRING &buf)
- {
- char *begin = line;
- const char *pt = buf.get();
- while (1){
- if (*pt == '\0'){
- if (pid == -1){
- *line = '\0';
- buf.setfrom ("");
- }else{
- *begin = '\0';
- }
- break;
- }else{
- char carac = *pt++;
- *line++ = carac;
- size--;
- if (size == 0 || carac == '\n'){
- buf.setfrom (pt);
- *line = '\0';
- break;
- }
- }
- }
- return line > begin ? 0 : -1;
- }
-
- /*
- Read one line of stderr if available (won't block).
- */
- PUBLIC int POPEN::readerr (char *line, int size)
- {
- return readline (line,size,errbuf);
- }
- /*
- Read one line of stdout if available (won't block).
- */
- PUBLIC int POPEN::readout (char *line, int size)
- {
- return readline (line,size,outbuf);
- }
-
- #ifdef TEST
-
- int simul_isdemo(){return 0;}
- int revision;
-
- int main (int argc, char *argv[])
- {
- if (argc > 1){
- char buf[1000];
- char *pt = buf;
- for (int i=1; i<argc; i++){
- pt += sprintf (pt,"%s ",argv[i]);
- }
- printf ("execute la commande :%s:\n",buf);
- POPEN p(buf);
- while (p.isok()){
- if (p.wait(10)>0){
- while (p.readout(buf,sizeof(buf)-1)!=-1){
- fputs (buf,stdout);
- }
- }else{
- break;
- }
- }
- }
- return 0;
- }
-
- #endif
-
-